using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;

internal class WebRequest
{
#if UNITY_ANDROID
    private const string activeBuildTarget  = "Android";
#elif UNITY_IPHONE
    private const string activeBuildTarget  = "iOS";
#elif UNITY_STANDALONE_WIN
    private const string activeBuildTarget = "StandaloneWindows64";
#endif

    private const string server_ip = "127.0.0.1";
    private const string server_format = "http://" + server_ip + ":80/" + activeBuildTarget + "/{0}";

    public float progress;

    private async Task Initialize()
    {
        var md5Path = Path.Combine(Application.persistentDataPath, "md5.txt");
        if (File.Exists(md5Path))
            return;

        var contnet = await ResourceHelper.ReadAsync("md5.txt");
        if (contnet == null)
        {
            Debug.LogError("load md5 fail!");
            return;
        }
        File.WriteAllBytes(md5Path, contnet);
        Debug.Log($"write {md5Path}");

    }
    internal async Task Donwload()
    {
        progress = 0;
        await Initialize();
        var serverConent = await GetServerFile("md5.txt");
        if (serverConent == null || serverConent.Length == 0)
            return;
        Debug.Log("check resource");
        var server = GetMd5Content(Encoding.UTF8.GetString(serverConent));
        var local = GetMd5Content(ReadLocalMd5());

        Stack<string> updateList = new Stack<string>();
        foreach (var item in server)
        {
            if (local.TryGetValue(item.Key, out var md5))
            {
                if (item.Value != md5)
                {
                    updateList.Push(item.Key);
                }
            }
            else
            {
                updateList.Push(item.Key);
            }
        }

        int index = 0;
        float total = updateList.Count;
        while (updateList.Count > 0)
        {
            var path = updateList.Pop();
            var result = await GetServerFile(path);
            if (result != null)
            {
                var localPath = Path.Combine(Application.persistentDataPath, path);
                var localDir = Path.GetDirectoryName(localPath);
                if (!Directory.Exists(localDir))
                    Directory.CreateDirectory(localDir);
                File.WriteAllBytes(localPath, result);
                Debug.Log($"update:{path}");
            }
            progress = index++ / total;
        }
        progress = 1;
        var md5Path = Path.Combine(Application.persistentDataPath, "md5.txt");
        File.WriteAllBytes(md5Path, serverConent);
        Debug.Log("check resource finish");
    }

    Dictionary<string, string> GetMd5Content(string content)
    {
        var lines = content.Split('\n');
        Dictionary<string, string> dict = new Dictionary<string, string>();
        foreach (var line in lines)
        {
            if (string.IsNullOrEmpty(line))
                continue;
            var array = line.Split('|');
            if (array.Length != 2)
                continue;
            dict[array[0]] = array[1];
        }
        return dict;
    }

    string ReadLocalMd5()
    {
        var md5Path = Path.Combine(Application.persistentDataPath, "md5.txt");
        if (!File.Exists(md5Path))
        {
            Debug.LogError("File md5 could not be found");
            return string.Empty;
        }

        var oldMd5 = File.ReadAllText(md5Path);
        if (string.IsNullOrEmpty(oldMd5))
        {
            Debug.LogError("md5 is null");
        }

        return oldMd5;
    }

    async Task<byte[]> GetServerFile(string path)
    {
        var url = string.Format(server_format, path);
        Debug.Log("request:" + url);
        var request = UnityWebRequest.Get(url);
        request.timeout = 5;
        request.SendWebRequest();

        while (!request.isDone)
        {
            await Task.Delay(1);
        }

        if (request.responseCode == 200)
        {
            if (string.IsNullOrEmpty(request.downloadHandler.error))
                return request.downloadHandler.data;
        }

        Debug.Log($"GetServerFile fail:[code]{request.responseCode} [path]{path}");
        return default;
    }
}